package cn.ydxiaoshuai.common.sdkpro;

import cn.ydxiaoshuai.common.api.vo.api.TargetParam;
import cn.ydxiaoshuai.common.api.vo.api.TemplateParam;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.http.AipRequest;
import com.baidu.aip.http.EBodyFormat;
import com.baidu.aip.util.Base64Util;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 小帅丶
 * @className AipFacePro
 * @Description 百度人脸识别邀测接口
 * @Date 2020/4/10-14:34
 **/
public class AipFacePro extends AipFace {
    /**皮肤光滑度检测接口*/
    public static String FACE_SKINSMOOTH_URL = "https://aip.baidubce.com/rest/2.0/face/v1/skin_smooth";
    /**痘斑痣检测接口*/
    public static String FACE_ACNESPOTMOLE_URL = "https://aip.baidubce.com/rest/2.0/face/v1/acnespotmole";
    /**人脸3D生成*/
    public static String FACE_3DPROCESS_URL = "https://aip.baidubce.com/rest/2.0/face/v1/face3dprocess";
    /**肤色检测*/
    public static String FACE_SKINCOLOR_URL = "https://aip.baidubce.com/rest/2.0/face/v1/skin_color";
    /**人脸融合*/
    public static String FACE_MERGE_URL = "https://aip.baidubce.com/rest/2.0/face/v1/merge";
    /**皱纹检测*/
    public static String FACE_WRINKLE_URL = "https://aip.baidubce.com/rest/2.0/face/v1/wrinkle";
    /**虚拟换妆*/
    public static String FACE_TRANSFER_URL = "https://aip.baidubce.com/rest/2.0/face/v1/transfer";
    /**黑眼圈眼袋检测*/
    public static String FACE_EYESATTR_URL = "https://aip.baidubce.com/rest/2.0/face/v1/eyesattr";
    /** 人脸驱动任务创建 */
    public static String  FACE_DRIVE_ADD = "https://aip.baidubce.com/rest/2.0/face/v1/vmfacedrive/task/add";
    /** 人脸驱动任务查询 */
    public static String  FACE_DRIVE_GET = "https://aip.baidubce.com/rest/2.0/face/v1/vmfacedrive/task/get";
    /** 虚拟主播视频生产（拟真版） */
    public static String  VIRTUAL_HUMAN_ADD = "https://aip.baidubce.com/rpc/2.0/creation/v1/virtualhuman/task/add";
    /** 虚拟主播视频生产结果查询（拟真版） */
    public static String  VIRTUAL_HUMAN_GET = "https://aip.baidubce.com/rpc/2.0/creation/v1/virtualhuman/task/get";
    /** 人脸驱动模板ID */
    public static String  TEMPLATE_ID = "template_v3TUE5MVRCDZ";

    public static String TEXT = "TEXT";

    public AipFacePro(String appId, String apiKey, String secretKey) {
        super(appId, apiKey, secretKey);
    }
    /**
     * 虚拟主播视频生产（拟真版）
     *
     * @param image - 图片信息(**总数据大小应小于4M**)
     * @param subtitle_text  - 内容文本(**汉字不大于1024**)
     * @return JSONObject
     */
    public JSONObject addVirtualHuman(byte[] image,String subtitle_text) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.addBody("appid",appId);
        String imageBase64 = Base64Util.encode(image);
        request.addBody("bg_image", imageBase64);
        request.addBody("subtitle_text", subtitle_text);
        request.addBody("subtitle_type", TEXT);
        request.setUri(VIRTUAL_HUMAN_ADD);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        postOperation(request);
        return requestServer(request);
    }


    /**
     * 虚拟主播视频生产结果查询（拟真版）
     *
     * @param taskId - 视频融合任务ID
     * @return JSONObject
     */
    public JSONObject getVirtualHuman(String taskId) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.addBody("task_id", taskId);
        request.addBody("appid",appId);
        request.setUri(VIRTUAL_HUMAN_GET);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        postOperation(request);
        return requestServer(request);
    }

    /**
     * 人脸驱动任务创建
     *
     * @param image - 图片信息(**总数据大小应小于4M**)
     * @return JSONObject
     */
    public JSONObject addFaceDrive(byte[] image) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.addBody("appid",appId);
        request.addBody("template_id", TEMPLATE_ID);
        String imageBase64 = Base64Util.encode(image);
        request.addBody("image", imageBase64);
        request.setUri(FACE_DRIVE_ADD);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        postOperation(request);
        return requestServer(request);
    }


    /**
     * 人脸驱动任务查询
     *
     * @param taskId - 视频融合任务ID
     * @return JSONObject
     */
    public JSONObject getFaceDrive(String taskId) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.addBody("appid",appId);
        request.addBody("task_id", taskId);
        request.setUri(FACE_DRIVE_GET);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        postOperation(request);
        return requestServer(request);
    }
    /**
     * 黑眼圈眼袋检测接口
     *
     * @param image - 图片信息(**总数据大小应小于10M**)，图片上传方式根据image_type来判断
     * @param imageType - 图片类型
     *                  <br> **BASE64**:图片的base64值，base64编码后的图片数据，编码后的图片大小不超过2M；
     *                  <br>**URL**:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长)；
     *                  <br>**FACE_TOKEN**: 人脸图片的唯一标识，调用人脸检测接口时，会为每个人脸图片赋予一个唯一的FACE_TOKEN，同一张图片多次检测得到的FACE_TOKEN是同一个。
     * @return JSONObject
     */
    public JSONObject eyesAttr(String image, String imageType) {
        return eyesAttr(image, imageType, 1);
    }
    /**
     * 黑眼圈眼袋检测接口
     *
     * @param image - 图片信息(**总数据大小应小于10M**)，图片上传方式根据image_type来判断
     * @param imageType - 图片类型
     *                  <br> **BASE64**:图片的base64值，base64编码后的图片数据，编码后的图片大小不超过2M；
     *                  <br>**URL**:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长)；
     *                  <br>**FACE_TOKEN**: 人脸图片的唯一标识，调用人脸检测接口时，会为每个人脸图片赋予一个唯一的FACE_TOKEN，同一张图片多次检测得到的FACE_TOKEN是同一个。
     * @param max_face_num  	最多处理人脸的数目. 默认值为1（仅检测图片中面积最大的那个人脸） 最大值10
     * @return JSONObject
     */
    public JSONObject eyesAttr(String image, String imageType,int max_face_num) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.addBody("appid",appId);
        request.addBody("image", image);
        request.addBody("image_type", imageType);
        if(max_face_num>10){
            request.addBody("max_face_num", 10);
        } else {
            request.addBody("max_face_num", max_face_num);
        }
        request.setUri(FACE_EYESATTR_URL);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        postOperation(request);
        return requestServer(request);
    }
    /**
     * 虚拟换妆接口
     *
     * @param source_image - 目标图信息，要求图片为清晰正脸 Object
     * @param reference_images - 模板图信息，要求被融合的人脸 Array
     * @param appid - app标识
     * @return JSONObject
     */
    public JSONObject faceTransfer(TargetParam source_image, TemplateParam reference_images, String appid) {
        AipRequest request = new AipRequest();
        preOperation(request);
        HashMap<String, Object> map = new HashMap<>();

        Map<String, Object> source_imageMap = new HashMap<>();
        source_imageMap.put("image_type", source_image.getImage_type().toString());
        source_imageMap.put("image",source_image.getImage());

        map.put("source_image", source_imageMap);

        Map<String, Object> reference_imagesMap = new HashMap<>();
        reference_imagesMap.put("image_type", reference_images.getImage_type().toString());
        reference_imagesMap.put("image",reference_images.getImage());

        List reference_imagesList = new ArrayList();
        reference_imagesList.add(reference_imagesMap);


        map.put("reference_images", reference_imagesList);
        map.put("appid", appid);

        request.addBody(map);
        request.setUri(FACE_TRANSFER_URL);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        System.out.println(request.getBodyStr());
        postOperation(request);
        return requestServer(request);
    }
    /**
     * 皱纹检测接口
     *
     * @param image - 图片信息(**总数据大小应小于10M**)，图片上传方式根据image_type来判断
     * @param imageType - 图片类型
     *                  <br> **BASE64**:图片的base64值，base64编码后的图片数据，编码后的图片大小不超过2M；
     *                  <br>**URL**:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长)；
     *                  <br>**FACE_TOKEN**: 人脸图片的唯一标识，调用人脸检测接口时，会为每个人脸图片赋予一个唯一的FACE_TOKEN，同一张图片多次检测得到的FACE_TOKEN是同一个。
     * @param max_face_num - 最多处理人脸的数目 默认值为1（仅检测图片中面积最大的那个人脸） 最大值10
     * @return JSONObject
     */
    public JSONObject wrinkle(String image, String imageType,int max_face_num) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        request.addBody("appid",appId);
        request.addBody("image", image);
        request.addBody("image_type", imageType);
        request.addBody("max_face_num", max_face_num);
        request.setUri(FACE_WRINKLE_URL);
        postOperation(request);
        return requestServer(request);
    }

    /**
     * 皱纹检测接口
     *
     * @param image - 图片信息(**总数据大小应小于10M**)，图片上传方式根据image_type来判断
     * @param imageType - 图片类型
     *                  <br> **BASE64**:图片的base64值，base64编码后的图片数据，编码后的图片大小不超过2M；
     *                  <br>**URL**:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长)；
     *                  <br>**FACE_TOKEN**: 人脸图片的唯一标识，调用人脸检测接口时，会为每个人脸图片赋予一个唯一的FACE_TOKEN，同一张图片多次检测得到的FACE_TOKEN是同一个。
     * @return JSONObject
     */
    public JSONObject wrinkle(String image, String imageType) {
        return wrinkle(image,imageType,1);
    }

    /**
     * 人脸融合接口
     *
     * @param image_template - 模板图信息，要求被融合的人脸
     * @param image_target - 目标图信息，要求图片为清晰正脸
     * @param merge_degree - 融合度 关系到融合图与目标图的相似度 越高则越相似
     *                      LOW:较低的融合度
     *                      NORMAL: 一般的融合度
     *                      HIGH: 较高的融合度
     *                      COMPLETE: 完全融合，其效果类似于换脸
     *                      默认COMPLETE
     * @return JSONObject
     */
    public JSONObject faceMerge(TemplateParam image_template, TargetParam image_target, String merge_degree) {
        AipRequest request = new AipRequest();
        preOperation(request);
        HashMap<String, Object> map = new HashMap<>();

        Map<String, Object> image_templateMap = new HashMap<>();
        image_templateMap.put("image",image_template.getImage());
        image_templateMap.put("image_type", image_template.getImage_type().toString());
        image_templateMap.put("quality_control", image_template.getQuality_control());
        image_templateMap.put("face_location", image_template.getFace_location());

        map.put("image_template", image_templateMap);

        Map<String, Object> image_targetMap = new HashMap<>();
        image_targetMap.put("image", image_target.getImage());
        image_targetMap.put("image_type", image_target.getImage_type().toString());
        image_templateMap.put("face_location", image_target.getFace_location());
        image_templateMap.put("quality_control", image_target.getQuality_control());

        map.put("image_target", image_targetMap);
        map.put("merge_degree", merge_degree);

        request.addBody(map);
        request.setUri(FACE_MERGE_URL);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        System.out.println(request.getBodyStr());
        postOperation(request);
        return requestServer(request);
    }

    /**
     * 人脸融合接口
     *
     * @param image_template - 模板图信息，要求被融合的人脸
     * @param image_target - 目标图信息，要求图片为清晰正脸
     * @return JSONObject
     */
    public JSONObject faceMerge(TemplateParam image_template, TargetParam image_target) {
        return faceMerge(image_template, image_target, "COMPLETE");
    }

    /**
     * 皮肤光滑度检测接口
     *
     * @param image - 图片信息(**总数据大小应小于10M**)，图片上传方式根据image_type来判断
     * @param imageType - 图片类型
     *                  <br> **BASE64**:图片的base64值，base64编码后的图片数据，编码后的图片大小不超过2M；
     *                  <br>**URL**:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长)；
     *                  <br>**FACE_TOKEN**: 人脸图片的唯一标识，调用人脸检测接口时，会为每个人脸图片赋予一个唯一的FACE_TOKEN，同一张图片多次检测得到的FACE_TOKEN是同一个。
     * @return JSONObject
     */
    public JSONObject skinSmooth(String image, String imageType) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.addBody("appid",appId);
        request.addBody("image", image);
        request.addBody("image_type", imageType);
        request.setUri(FACE_SKINSMOOTH_URL);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        postOperation(request);
        return requestServer(request);
    }

    /**
     * 痘斑痣检测接口
     *
     * @param image - 图片信息(**总数据大小应小于10M**)，图片上传方式根据image_type来判断
     * @param imageType - 图片类型
     *                  <br> **BASE64**:图片的base64值，base64编码后的图片数据，编码后的图片大小不超过2M；
     *                  <br>**URL**:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长)；
     *                  <br>**FACE_TOKEN**: 人脸图片的唯一标识，调用人脸检测接口时，会为每个人脸图片赋予一个唯一的FACE_TOKEN，同一张图片多次检测得到的FACE_TOKEN是同一个。
     * @return JSONObject
     */
    public JSONObject acnespotmole(String image, String imageType) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.addBody("image", image);
        request.addBody("appid",appId);
        request.addBody("image_type", imageType);
        request.setUri(FACE_ACNESPOTMOLE_URL);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        postOperation(request);
        return requestServer(request);
    }
    /**
     * 痘斑痣检测接口
     *
     * @param image - 图片信息(**总数据大小应小于10M**)，图片上传方式根据image_type来判断
     * @param imageType - 图片类型
     *                  <br> **BASE64**:图片的base64值，base64编码后的图片数据，编码后的图片大小不超过2M；
     *                  <br>**URL**:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长)；
     *                  <br>**FACE_TOKEN**: 人脸图片的唯一标识，调用人脸检测接口时，会为每个人脸图片赋予一个唯一的FACE_TOKEN，同一张图片多次检测得到的FACE_TOKEN是同一个。
     * @return JSONObject
     */
    public JSONObject skinColor(String image, String imageType) {
        AipRequest request = new AipRequest();
        preOperation(request);
        request.addBody("image_type", imageType);
        request.addBody("image", image);
        request.addBody("appid",appId);
        request.setUri(FACE_SKINCOLOR_URL);
        request.setBodyFormat(EBodyFormat.RAW_JSON);
        postOperation(request);
        return requestServer(request);
    }
}
